Imports System.Reflection
Imports System.Collections.Generic
Imports System.Linq
Imports System.IO
Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Audio
Imports Microsoft.Xna.Framework.Content
Imports Microsoft.Xna.Framework.GamerServices
Imports Microsoft.Xna.Framework.Graphics
Imports Microsoft.Xna.Framework.Input
Imports Microsoft.Xna.Framework.Media
Imports Microsoft.Xna.Framework.Input.Touch



Public Class Tile
	Public nextTileType As Enumeration.TileType = Enumeration.TileType.space

	Public Texture As Texture2D
	'private float Depth = 0.1f;
	Public collision As Enumeration.TileCollision
	Public Type As Enumeration.TileType
	Public tileAnimation As New AnimationSequence()
	'private StateTileElement stateTileElement = new StateTileElement();
	Public tileState As New TileState()
	'contains object like sword, potion...
	Public item As Item = Nothing


	Public Shared GROUND As Integer = 20
	'20;//18; //Height of the floor ground
	Public Shared WIDTH As Integer = 64
	'used for build the grid of room
	Public Shared HEIGHT As Integer = 126
	'used for build the grid of room 
	Public Shared REALHEIGHT As Integer = 148
	'used for build view of romm
	Public Shared REALWIDTH As Integer = 128
	'used for build view of romm
	Public Shared PERSPECTIVE As Integer = 26
	'26 isometric shift x right
	Public Shared ReadOnly Size As New Vector2(WIDTH, HEIGHT)

	Public Shared MASK_FLOOR As New Rectangle(0, 128, 62, 20)
	'floor 
	Public Shared MASK_POSTS As New Rectangle(0, 0, 54, 148)
	'gate
	Public Shared MASK_BLOCK As New Rectangle(0, 0, 64, 148)
	'block 
	Public Shared MASK_DOOR As New Rectangle(50, 0, 13, 148)
	'door

	'(0, 128, 62, 20);


	Private flip As SpriteEffects = SpriteEffects.None
	'private List<Tile> _tileReference = new List<Tile>();
	'protected List<Tile> tileReference
	'{
	'    get { return _tileReference; }
	'    set { _tileReference = value; }
	'}

	'private Maze maze;
	Protected room As RoomNew

	Private _position As Position
	Public Property Position() As Position
		Get
			Return _position
		End Get
		Set
			_position = value
		End Set
	End Property

	'to determine how to draw walls, calculate in room construction algorithm
	Private _panelInfo As Integer
	Public Property panelInfo() As Integer
		Get
			Return _panelInfo
		End Get
		Set
			_panelInfo = value
		End Set
	End Property


	Public ReadOnly Property Coordinates() As Vector2
		Get
			Dim x As Integer = CInt(Math.Truncate(Math.Floor(CSng(_position.X) / Tile.WIDTH)))
			Dim y As Integer = CInt(Math.Truncate(Math.Ceiling((CSng(_position.Y) - RoomNew.BOTTOM_BORDER) / Tile.HEIGHT)))

			Return New Vector2(x, y)
		End Get
	End Property


	'static for share purposes
	Private Shared m_tileSequence As New List(Of Sequence)()
	Public ReadOnly Property TileSequence() As List(Of Sequence)
		Get
			Return m_tileSequence
		End Get
	End Property



	Public Sub New()
	End Sub

	Public Sub New(room As RoomNew, Content As ContentManager, tileType As Enumeration.TileType, state As Enumeration.StateTile, eitem As Enumeration.Items, NextTileType__1 As Enumeration.TileType)
		Me.room = room
		nextTileType = NextTileType__1

		Dim ax As New System.Xml.Serialization.XmlSerializer(m_tileSequence.[GetType]())

		Dim txtReader As Stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(PrinceOfPersiaGame.CONFIG_PATH_CONTENT & PrinceOfPersiaGame.CONFIG_PATH_SEQUENCES & tileType.ToString().ToUpper() & "_sequence.xml")
		'TextReader txtReader = File.OpenText(PrinceOfPersiaGame.CONFIG_PATH_CONTENT + PrinceOfPersiaGame.CONFIG_PATH_SEQUENCES + tileType.ToString().ToUpper() + "_sequence.xml");


		m_tileSequence = DirectCast(ax.Deserialize(txtReader), List(Of Sequence))

		For Each s As Sequence In m_tileSequence
			s.Initialize(Content)
		Next

		'Search in the sequence the right type
		Dim result As Sequence = m_tileSequence.Find(Function(s As Sequence) s.name = state.ToString().ToUpper())

		If result IsNot Nothing Then
			'AMF to be adjust....
			result.frames(0).SetTexture(Content.Load(Of Texture2D)(PrinceOfPersiaGame.CONFIG_TILES & result.frames(0).value))

			collision = result.collision
			Texture = result.frames(0).texture
		End If
		Type = tileType


		'change statetile element
		Dim stateTileElement As New StateTileElement()
		stateTileElement.state = state
		tileState.Add(stateTileElement)
		tileAnimation.PlayAnimation(m_tileSequence, tileState.Value())

		'load item
		Select Case eitem
			Case Enumeration.Items.flask
				item = New Flask(Content)
				Exit Select
			Case Enumeration.Items.sword
				item = New Sword(Content)
				Exit Select

		End Select
	End Sub

	''' <summary>
	''' Handles input, performs physics, and animates the player sprite.
	''' </summary>
	''' <remarks>
	''' We pass in all of the input states so that our game is only polling the hardware
	''' once per frame. We also pass the game's orientation because when using the accelerometer,
	''' we need to reverse our motion when the orientation is in the LandscapeRight orientation.
	''' </remarks>
	Public Sub Update(gameTime As GameTime, keyboardState As KeyboardState, gamePadState As GamePadState, touchState As TouchCollection, accelState As AccelerometerState, orientation As DisplayOrientation)
		HandleCollision()

		If Me.[GetType]() Is GetType(Spikes) Then
			DirectCast(Me, Spikes).elapsedTimeOpen += CSng(gameTime.ElapsedGameTime.TotalSeconds)
			If DirectCast(Me, Spikes).elapsedTimeOpen > DirectCast(Me, Spikes).timeOpen Then
				DirectCast(Me, Spikes).Close()
			End If
		End If


		If Me.[GetType]() Is GetType(Gate) Then
			DirectCast(Me, Gate).elapsedTimeOpen += CSng(gameTime.ElapsedGameTime.TotalSeconds)
			If DirectCast(Me, Gate).elapsedTimeOpen > DirectCast(Me, Gate).timeOpen Then
				DirectCast(Me, Gate).Close()
			End If
		End If

		If Me.[GetType]() Is GetType(PressPlate) Then
			DirectCast(Me, PressPlate).elapsedTimeOpen += CSng(gameTime.ElapsedGameTime.TotalSeconds)
			If DirectCast(Me, PressPlate).elapsedTimeOpen > DirectCast(Me, PressPlate).timeOpen And DirectCast(Me, PressPlate).State = Enumeration.StateTile.dpressplate Then
				DirectCast(Me, PressPlate).DePress()
			End If
		End If

		If Me.[GetType]() Is GetType(Loose) Then
			If DirectCast(Me, Loose).tileState.Value().state = Enumeration.StateTile.loose Then
				DirectCast(Me, Loose).elapsedTimeOpen += CSng(gameTime.ElapsedGameTime.TotalSeconds)
				If DirectCast(Me, Loose).elapsedTimeOpen > DirectCast(Me, Loose).timeFall Then
					DirectCast(Me, Loose).Fall()
				End If
			End If
		End If

		Dim elapsed As Single = CSng(gameTime.ElapsedGameTime.TotalSeconds)
		tileAnimation.UpdateFrameTile(elapsed, _position, flip, tileState)

	End Sub

	Public Sub HandleCollision()

		If Me.Type = Enumeration.TileType.loose Then
			If Me.tileState.Value().state <> Enumeration.StateTile.loosefall Then
				Return
			End If

			Dim r As New Rectangle(CInt(Math.Truncate(Position.X)), CInt(Math.Truncate(Position.Y)), Tile.WIDTH, Tile.HEIGHT)
			Dim v As Vector4 = room.getBoundTiles(r)
			Dim tileBounds As Rectangle = room.GetBounds(CInt(Math.Truncate(v.X)), CInt(Math.Truncate(v.W)))

			Dim depth As Vector2 = RectangleExtensions.GetIntersectionDepth(tileBounds, r)
			Dim tileType As Enumeration.TileType = room.[GetType](CInt(Math.Truncate(v.X)), CInt(Math.Truncate(v.W)))
			Dim tileCollision As Enumeration.TileCollision = room.GetCollision(CInt(Math.Truncate(v.X)), CInt(Math.Truncate(v.W)))
			'Tile tile = room.GetTile(new Vector2((int)v.X, (int)v.W));
			If tileCollision = Enumeration.TileCollision.Platform Then
				'if (tileType == Enumeration.TileType.floor)
				If depth.Y >= Tile.HEIGHT - Tile.PERSPECTIVE Then
					SyncLock room.tilesTemporaney
						room.tilesTemporaney.Remove(Me)
					End SyncLock
					'Vector2 vs = new Vector2(this.Position.X, this.Position.Y);
					If tileType = Enumeration.TileType.loose Then
						Dim l As Loose = DirectCast(room.GetTile(CInt(Math.Truncate(v.X)), CInt(Math.Truncate(v.W))), Loose)
						l.Fall(True)
					Else
						DirectCast(Maze.dContentRes(PrinceOfPersiaGame.CONFIG_SOUNDS & "tile crashing into the floor".ToUpper()), SoundEffect).Play()
						room.SubsTile(Coordinates, Enumeration.TileType.rubble)
					End If

				End If
			End If


			'if (_position.Y >= RoomNew.BOTTOM_LIMIT - Tile.HEIGHT - Tile.PERSPECTIVE)
			If _position.Y >= RoomNew.BOTTOM_LIMIT - Tile.PERSPECTIVE Then
				'remove tiles from tilesTemporaney
				SyncLock room.tilesTemporaney
					room.tilesTemporaney.Remove(Me)
				End SyncLock
				'exit from DOWN room
				Dim roomDown As RoomNew = room.maze.DownRoom(room)
				room = roomDown
				_position.Y = RoomNew.TOP_LIMIT - 10

				SyncLock room.tilesTemporaney
					room.tilesTemporaney.Add(Me)
				End SyncLock



			End If
		End If
	End Sub

End Class

